package lrc2video.happy.lyrics.utils;

import lrc2video.happy.lyrics.model.LyricsLineInfo;
import lrc2video.zlm.tool.lv.common.Constants;
import lrc2video.zlm.tool.lv.model.PaintColorInfo;
import org.apache.commons.io.FilenameUtils;
import top.xzxsrq.common.utils.FileUtilsZX;
import top.xzxsrq.utils.PathUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.TreeMap;
import java.util.concurrent.Callable;

public class ImageCallable implements Callable<Integer> {
    private int width;
    private int height;
    private Font kscFont;
    private LyricsUtils lyricsUtils;
    private TreeMap<Integer, LyricsLineInfo> lyricsLineTreeMap;
    private int progress;
    private int offsetTime;
    /**
     * 当前歌词的所在行数
     */
    private int lyricsLineNum = -1;
    /**
     * 高亮歌词当前的其实x轴绘制坐标
     **/
    private float highLightLrcMoveX;
    /**
     * 当前歌词的第几个字
     */
    private int lyricsWordIndex = -1;
    /**
     * 当前歌词第几个字 已经播放的时间
     */
    private int lyricsWordHLEDTime = 0;
    /**
     * 当前歌词第几个字 已经播放的长度
     */
    private float lineLyricsHLWidth = 0;
    /**
     * 歌词每行的间隔
     */
    private float INTERVAL;
    private File lrcFile;
    private int maxProgress;

    public ImageCallable(
            File lrcFile,
            int width,
            int height,
            Font kscFont,
            LyricsUtils lyricsUtils,
            TreeMap<Integer, LyricsLineInfo> lyricsLineTreeMap,
            int progress,
            int offsetTime,
            int paddingHeight,
            int maxProgress

    ) {
        this.lrcFile = lrcFile;
        this.width = width;
        this.height = height;
        this.kscFont = kscFont;
        this.lyricsUtils = lyricsUtils;
        this.lyricsLineTreeMap = lyricsLineTreeMap;
        this.progress = progress;
        this.offsetTime = offsetTime;
        this.INTERVAL = paddingHeight;
        this.maxProgress = maxProgress;
    }

    @Override
    public Integer call() throws Exception {
        int newLyricsLineNum = lyricsUtils.getLineNumber(lyricsLineTreeMap, progress, offsetTime);
        if (newLyricsLineNum != lyricsLineNum) {
            lyricsLineNum = newLyricsLineNum;
            highLightLrcMoveX = 0;
        }
        if (lyricsLineNum == -1) {
            lyricsLineNum = 0;
        }
        lyricsWordIndex = lyricsUtils.getDisWordsIndex(lyricsLineTreeMap, lyricsLineNum, progress, offsetTime);

        lyricsWordHLEDTime = lyricsUtils.getDisWordsIndexLenTime(lyricsLineTreeMap, lyricsLineNum, progress,
                offsetTime);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        // 获取Graphics2D
        Graphics2D g2d = image.createGraphics();
        // ---------- 增加下面的代码使得背景透明 -----------------
        image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        g2d.dispose();
        g2d = image.createGraphics();
        // ---------- 背景透明代码结束 -----------------

        // 设置“抗锯齿”的属性
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        //
        // g2d.setFont(new Font("宋体", Font.BOLD, (int) SCALEIZEWORDDEF));
        g2d.setFont(kscFont);

        // 先设置当前歌词，之后再根据索引判断是否放在左边还是右边
        LyricsLineInfo lyricsLineInfo = lyricsLineTreeMap.get(lyricsLineNum);
        // 当行歌词
        String currentLyrics = lyricsLineInfo.getLineLyrics();

        FontMetrics fm = g2d.getFontMetrics();
        Rectangle2D rc = fm.getStringBounds(currentLyrics, g2d);

        // 文字占据的宽度和高度
        int currentTextWidth = (int) rc.getWidth();
        int currentTextHeight = fm.getHeight();

        if (lyricsWordIndex != -1) {
            String lyricsWords[] = lyricsLineInfo.getLyricsWords();
            int wordsDisInterval[] = lyricsLineInfo.getWordsDisInterval();
            // 当前歌词之前的歌词
            String lyricsBeforeWord = "";
            for (int i = 0; i < lyricsWordIndex; i++) {
                lyricsBeforeWord += lyricsWords[i];
            }
            // 当前歌词
            String lyricsNowWord = lyricsWords[lyricsWordIndex].trim();// 去掉空格

            Rectangle2D rc2 = fm.getStringBounds(lyricsBeforeWord, g2d);
            // 当前歌词之前的歌词长度
            int lyricsBeforeWordWidth = (int) rc2.getWidth();

            Rectangle2D rc3 = fm.getStringBounds(lyricsNowWord, g2d);
            // 当前歌词长度
            float lyricsNowWordWidth = (int) rc3.getWidth();

            float len = lyricsNowWordWidth / wordsDisInterval[lyricsWordIndex] * lyricsWordHLEDTime;
            lineLyricsHLWidth = lyricsBeforeWordWidth + len;
        } else {
            // 整行歌词
            lineLyricsHLWidth = currentTextWidth;
        }
        // 当前歌词行的x坐标
        float textX = 0;
        // 当前歌词行的y坐标 一定是居中的
        float textY = (float) (height - currentTextHeight) / 2;
        if (currentTextWidth < width) {
            // 居中
            textX = (float) (width - currentTextWidth) / 2;
        }
        // 处理高亮
        // 高亮最大到一半宽度就滚动
        float v = (float) width / 2;
        if (currentTextWidth > width && lineLyricsHLWidth > v) {
            highLightLrcMoveX = lineLyricsHLWidth - v;
            // 如果歌词宽度大于view的宽，则需要动态设置歌词的起始x坐标，以实现水平滚动
            textX -= highLightLrcMoveX;
        }

        // 画接下来的歌词，歌词超过屏幕就不在画
        int nextLineNum = lyricsLineNum + 1;
        float nextTextX;
        float nextTextY = textY + INTERVAL + fm.getHeight();
        while (nextTextY < height && nextLineNum < lyricsLineTreeMap.size()) {
            // 获取这一行的数据
            String lineLyrics = lyricsLineTreeMap.get(nextLineNum).getLineLyrics();
            Rectangle2D rc4 = fm.getStringBounds(lineLyrics, g2d);
            double width1 = rc4.getWidth();
            if (width1 < width) {
                nextTextX = (float) ((width - width1) / 2);
            } else {
                nextTextX = 0;
            }
            drawString(g2d, fm, nextTextX, nextTextY, lineLyrics);
            // 继续画下一行
            nextLineNum++;
            nextTextY = nextTextY + fm.getHeight() + INTERVAL;
        }
        // 画接上面的歌词，歌词超过屏幕就不在画
        int lastLineNum = lyricsLineNum - 1;
        float lastTextX;
        float lastTextY = textY - INTERVAL - fm.getHeight();
        while ((lastTextY + fm.getHeight()) > 0 && lastLineNum > 0) {
            // 获取这一行的数据
            String lineLyrics = lyricsLineTreeMap.get(lastLineNum).getLineLyrics();
            Rectangle2D rc4 = fm.getStringBounds(lineLyrics, g2d);
            double width1 = rc4.getWidth();
            if (width1 < width) {
                lastTextX = (float) ((width - width1) / 2);
            } else {
                // 显示在最后面
                lastTextX = (float) (width - width1);
            }
            drawString(g2d, fm, lastTextX, lastTextY, lineLyrics);
            // 继续画上一行
            lastLineNum--;
            lastTextY = lastTextY - fm.getHeight() - INTERVAL;
        }
        int textHeight = fm.getHeight();
        LinearGradientPaint paintHLDEF = initPaintHLDEFColor(textX, textY, textHeight);
        g2d.setPaint(paintHLDEF);
        // 画当前歌词
        g2d.drawString(currentLyrics, textX, textY);
        // 这里不知为何还要减去fm.getDescent() + fm.getLeading() 绘画时才能把全文字绘画完整
        int clipY = (int) (textY - currentTextHeight + (fm.getDescent() + fm.getLeading()));
        g2d.clipRect((int) textX, clipY, (int) lineLyricsHLWidth, currentTextHeight);
        LinearGradientPaint paintHLED = initPaintHLEDColor(textX, textY, textHeight);
        g2d.setPaint(paintHLED);
        g2d.drawString(currentLyrics, textX, textY);
        String lrcFileImagePath = getLrcFileImagePath(lrcFile) + File.separator;
        File lrcFileImageFile = new File(lrcFileImagePath);
        if (!lrcFileImageFile.exists()) {
            lrcFileImageFile.mkdirs();
        }
        try {
            ImageIO.write(image, "png", new File(
                    lrcFileImagePath + addZeroForNum(progress + "", ((maxProgress + 100) + "").length()) + ".png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return progress;
    }

    public static String addZeroForNum(String str, int strLength) {
        int strLen = str.length();
        StringBuffer sb = null;
        while (strLen < strLength) {
            sb = new StringBuffer();
            sb.append("0").append(str);// 左补0
            // sb.append(str).append("0");//右补0
            str = sb.toString();
            strLen = str.length();
        }
        return str;
    }

    /**
     * @param lrcFile
     * @return
     */
    public static String getBaseName(File lrcFile) {
        return FilenameUtils.getBaseName(lrcFile.getAbsolutePath());
    }

    public static String getLrcFileImagePath(File lrcFile) {
        String baseName = getBaseName(lrcFile);
        String lrcFileImagePath = lrcFile.getParent() + File.separator + baseName;
        return PathUtils.pathStandardization(lrcFileImagePath);
    }

    public static String getAssFilePath(File lrcFile) {
        String baseName = getBaseName(lrcFile);
        String outFile = lrcFile.getParent() + File.separator + baseName + ".ass";
        return PathUtils.pathStandardization(outFile);
    }

    public static void delLrcFileImagePath(File lrcFile) throws IOException {
        // 删除对应的文件
        String lrcFileImagePath = getLrcFileImagePath(lrcFile);
        File file2 = new File(lrcFileImagePath);
        if (file2.exists() && file2.isDirectory()) {
            FileUtilsZX.deleteDirectory(file2);
        }
    }

    public static String getOutFilePath(File lrcFile) {
        String baseName = getBaseName(lrcFile);
        String outFile = lrcFile.getParent() + File.separator + baseName + ".mp4";
        return PathUtils.pathStandardization(outFile);
    }

    public static String getAudioFilePath(File lrcFile) {
        String baseName = getBaseName(lrcFile);
        String audioFilePath = lrcFile.getParent() + File.separator + baseName + ".mp3";
        return PathUtils.pathStandardization(audioFilePath);
    }

    /**
     * 初始化高亮字体的渐变颜色
     */
    private LinearGradientPaint initPaintHLEDColor(float x, float y, int height) {
        PaintColorInfo colorInfo = Constants.DESLRCREADEDCOLORS.get(Constants.desktopLrcIndex);
        LinearGradientPaint paintHLED = new LinearGradientPaint(x, y - height, x, y, colorInfo.getFractions(),
                colorInfo.getColors());
        return paintHLED;
    }

    /**
     * 画文字
     *
     * @param g2d
     * @param fm
     * @param x
     * @param y
     * @param text
     */
    private void drawString(Graphics2D g2d, FontMetrics fm, float x, float y, String text) {
        drawBackground(g2d, text, x, y);
        LinearGradientPaint paintHLDEF = initPaintHLDEFColor(x, y, fm.getHeight());
        g2d.setPaint(paintHLDEF);
        g2d.drawString(text, x, y);
    }

    /**
     * 描绘轮廓
     *
     * @param g2d
     * @param string
     * @param x
     * @param y
     */
    private void drawBackground(Graphics2D g2d, String string, float x, float y) {
        g2d.setColor(new Color(0, 0, 0, 200));
        g2d.drawString(string, x - 1, y);
        g2d.drawString(string, x + 1, y);
        g2d.drawString(string, x, y + 1);
        g2d.drawString(string, x, y - 1);

    }

    /**
     * 初始化默认字体的渐变颜色
     */
    private LinearGradientPaint initPaintHLDEFColor(float x, float y, int height) {
        PaintColorInfo colorInfo = Constants.DESLRCNOREADCOLORS.get(Constants.desktopLrcIndex);
        LinearGradientPaint paintHLDEF = new LinearGradientPaint(x, y - height, x, y, colorInfo.getFractions(),
                colorInfo.getColors());
        return paintHLDEF;
    }
}
